package com.zhuangxiaoyan.designpattern.clonemodel;

import org.junit.Test;
import java.io.*;

class DeepClonableTarget implements Serializable, Cloneable {

    private String cloneName;
    private String cloneClass;

    public DeepClonableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }

    public String getCloneName() {
        return cloneName;
    }

    public void setCloneName(String cloneName) {
        this.cloneName = cloneName;
    }

    public String getCloneClass() {
        return cloneClass;
    }

    public void setCloneClass(String cloneClass) {
        this.cloneClass = cloneClass;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

/**
 * @description 重写 clone 方法来实现深拷贝
  * @param: null
 * @date: 2022/3/27 9:48
 * @return:
 * @author: xjl
*/
class DeepPrototype implements Serializable, Cloneable {
    private String name;
    private DeepClonableTarget deepClonableTarget;

    public DeepPrototype() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public DeepClonableTarget getDeepClonableTarget() {
        return deepClonableTarget;
    }

    public void setDeepClonableTarget(DeepClonableTarget deepClonableTarget) {
        this.deepClonableTarget = deepClonableTarget;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //基本数据类型拷贝
        Object object = super.clone();
        //引用类型拷贝
        DeepPrototype deepPrototype = (DeepPrototype) object;
        deepPrototype.deepClonableTarget = (DeepClonableTarget) deepClonableTarget.clone();
        return object;
    }
}

/**
 * @description 深拷贝方式 通过对象序列化实现深拷贝
 * @param: null
 * @date: 2022/3/27 9:41
 * @return:
 * @author: xjl
 */
class DeepPrototypeV2 implements Serializable, Cloneable {
    private String name;
    private DeepClonableTarget deepClonableTarget;

    public DeepPrototypeV2() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public DeepClonableTarget getDeepClonableTarget() {
        return deepClonableTarget;
    }

    public void setDeepClonableTarget(DeepClonableTarget deepClonableTarget) {
        this.deepClonableTarget = deepClonableTarget;
    }

    /**
     * @description 通过对象序列化实现深拷贝
      * @param:
     * @date: 2022/3/27 9:55
     * @return: com.zhuangxiaoyan.designpattern.clonemodel.DeepPrototype
     * @author: xjl
    */
    public DeepPrototypeV2 deepClone() {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            return (DeepPrototypeV2) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
                if (bis != null) {
                    bis.close();
                }
                if (oos != null) {
                    oos.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * @Classname DeepTestDemo
 * @Description
 * @Date 2022/3/27 9:38
 * @Created by xjl
 */
public class DeepTestDemo {

    @Test
    public void testv1() throws CloneNotSupportedException {
        DeepPrototype prototype = new DeepPrototype();
        prototype.setName("庄小焱");
        prototype.setDeepClonableTarget(new DeepClonableTarget("及时雨", "及时雨的类"));

        DeepPrototype clone1 = (DeepPrototype) prototype.clone();
        DeepPrototype clone2 = (DeepPrototype) prototype.clone();
        DeepPrototype clone3 = (DeepPrototype) prototype.clone();
        DeepPrototype clone4 = (DeepPrototype) prototype.clone();
        DeepPrototype clone5 = (DeepPrototype) prototype.clone();

        System.out.println(prototype.getName() + ", " + prototype.getDeepClonableTarget().hashCode()); // 庄小焱, 1554874502
        System.out.println(clone1.getName() + ", " + clone1.getDeepClonableTarget().hashCode()); // 庄小焱, 1846274136
        System.out.println(clone2.getName() + ", " + clone2.getDeepClonableTarget().hashCode()); // 庄小焱, 1639705018
        System.out.println(clone3.getName() + ", " + clone3.getDeepClonableTarget().hashCode()); // 庄小焱, 1627674070
        System.out.println(clone4.getName() + ", " + clone4.getDeepClonableTarget().hashCode()); // 庄小焱, 1360875712
        System.out.println(clone5.getName() + ", " + clone5.getDeepClonableTarget().hashCode()); // 庄小焱, 1625635731
    }

    @Test
    public void testv2() throws CloneNotSupportedException {
        DeepPrototypeV2 prototypev2 = new DeepPrototypeV2();
        prototypev2.setName("庄小焱");
        prototypev2.setDeepClonableTarget(new DeepClonableTarget("zhuangxiaoyan", "yatou"));

        DeepPrototypeV2 clone1 = prototypev2.deepClone();
        DeepPrototypeV2 clone2 = prototypev2.deepClone();
        DeepPrototypeV2 clone3 = prototypev2.deepClone();
        DeepPrototypeV2 clone4 = prototypev2.deepClone();
        DeepPrototypeV2 clone5 = prototypev2.deepClone();

        System.out.println(prototypev2.getName() + ", " + prototypev2.getDeepClonableTarget().hashCode()); // 庄小焱,644117698
        System.out.println(clone1.getName() + ", " + clone1.getDeepClonableTarget().hashCode());           // 庄小焱, 317574433
        System.out.println(clone2.getName() + ", " + clone2.getDeepClonableTarget().hashCode());           // 庄小焱, 885284298
        System.out.println(clone3.getName() + ", " + clone3.getDeepClonableTarget().hashCode());           // 庄小焱, 1389133897
        System.out.println(clone4.getName() + ", " + clone4.getDeepClonableTarget().hashCode());           // 庄小焱, 1534030866
        System.out.println(clone5.getName() + ", " + clone5.getDeepClonableTarget().hashCode());           // 庄小焱, 664223387
    }
}